#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
  /* code */
  /*
  
  */
  int b1 = 0b1011;
  int b2 = 0b1100;

  /*
  按位或运算
  1 | 1 = 1
  1 | 0 = 1
  0 | 1 = 1
  0 | 0 = 0
  */
  /*
  1011
  1100 |
  ------
  1111
  */
  int b3 = b1 | b2; // 0b1111

  /*
  按位与运算
  1 & 1 = 1
  1 & 0 = 0
  0 & 1 = 0
  0 & 0 = 0
  */
  /*
  1011
  1100 &
  ------
  1000
  */
  int b4 = b1 & b2; // 0b1000

  /*
  低位对齐，高位补零
  0b1101 & 
  0b0011
  -------
  0b0001
  */

  // << [数字] 二进制位移符号
  // b1 1011
  //     101
  //      10
  //       0
  //  101100  
  int b5 = b1 << 2; // 低位补 0 0b101100
  int b6 = b1 >> 2; // 去掉最低位

  // 0x33 十六进制数，用 0x 前缀开头
  // 0x33 -二进制-> 0b00110011
  // 1. 从左向右，把每一个十六进制数变成一个 4 位二进制数
  // 2. 把这些二进制数连在一起
  // 0b0011 0b0011
  // 0b00110011
  // 0x55 -二进制-> 0b01010101
  // 0xA7 -二进制-> 0b10100111

  int x = 2;
  x = (x | x << 2) & 0x33; // 0b10

  cout << x << endl;

  // 负数的二进制怎么表示
  // 1. 算正数的二进制
  // 2. 把正数的二进制按位取反，1->0，0->1
  // 3. 把取反的结果 + 1
  // -5
  // 5 = 0b0101 -> 0b1010 + 1 = 0b1011 = -5
  // 6 = 0b0110 -> 0b1001 + 1 = 0b1010 = -6
  // 7 = 0b0111 -> 0b1000 + 1 = 0b1001 = -7 
  //
  // 0b1011 = -5
  // 0b1010 = -6
  // 0b1001 = -7
  // -8
  // 8 = 0b01000 = 0b10111 + 1 = 0b11000
  /*
  10111 +
  00001
  -------
  11000 
  */ 

  // 4 个二进制位表达
  // -3 = 0b1101   4-bit
  //    = 0b11101  5-bit
  //    = 0b111101 6-bit

  // 负数扩大位数在左边补 1
  // 正数扩大位数在左边补 0

  // 对于一个可以表达正负数的二进制数来说，
  // 是否存在二进制最高位为 1 的正数呢？
  // 不存在

  // 对于一个 4 个二进制位的数字来说
  // 存在 0b1000 这样的正数么？
  // 如果在同时表达正负数的情况下，不能用 4 个二进制位表达 8 了，0b01000

  // 当同时存在正负数的时候，我们管二进制数的最高位，叫做符号位。
  // 扩展位数的时候，正数在左边补 0，负数在左边补 1。

  // -8 ~ 7
  // 对于一个 4 个位数的有符号二进制来说，它能表达的最大正数是？0b0111 = 7
  //                           它能表达的最小负数是？0b1000 = -8

  // 0 ~ 15
  // 对于一个 4 个位数的无符号二进制来说，它能表达的最大正数是？0b1111 = 15
  //                                它的最小值是？0b0000 = 0

  // bbbb
  // 1011

  // 1 字节 - 8 个二进制位
  int x;
  return 0;
}
